//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

use crate::notice_decode::new_wrong_session_notice;
use proto_gen_rust::user_todo_api::user_todo_api_client::UserTodoApiClient;
use proto_gen_rust::user_todo_api::*;
use tauri::{
    plugin::{Plugin, Result as PluginResult}, AppHandle, Invoke, PageLoadPayload, Runtime, Window
};


#[tauri::command]
async fn create_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: CreateTodoRequest,
) -> Result<CreateTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.create_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == create_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("create_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn update_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: UpdateTodoRequest,
) -> Result<UpdateTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.update_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == update_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("update_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn count_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: CountTodoRequest,
) -> Result<CountTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.count_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == count_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("count_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn list_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ListTodoRequest,
) -> Result<ListTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.list_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == list_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("list_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn get_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: GetTodoRequest,
) -> Result<GetTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.get_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == get_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("get_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn remove_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: RemoveTodoRequest,
) -> Result<RemoveTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.remove_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == remove_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("remove_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

#[tauri::command]
async fn clear_todo<R: Runtime>(
    app_handle: AppHandle<R>,
    window: Window<R>,
    request: ClearTodoRequest,
) -> Result<ClearTodoResponse, String> {
    let chan = crate::get_grpc_chan(&app_handle).await;
    if (&chan).is_none() {
        return Err("no grpc conn".into());
    }
    let mut client = UserTodoApiClient::new(chan.unwrap());
    match client.clear_todo(request).await {
        Ok(response) => {
            let inner_resp = response.into_inner();
            if inner_resp.code == clear_todo_response::Code::WrongSession as i32 {
                if let Err(err) =
                    window.emit("notice", new_wrong_session_notice("clear_todo".into()))
                {
                    println!("{:?}", err);
                }
            }
            return Ok(inner_resp);
        }
        Err(status) => Err(status.message().into()),
    }
}

pub struct UserTodoApiPlugin<R: Runtime> {
    invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync + 'static>,
}

impl<R: Runtime> UserTodoApiPlugin<R> {
    pub fn new() -> Self {
        Self {
            invoke_handler: Box::new(tauri::generate_handler![
                create_todo,
                update_todo,
                count_todo,
                list_todo,
                get_todo,
                remove_todo,
                clear_todo,
            ]),
        }
    }
}

impl<R: Runtime> Plugin<R> for UserTodoApiPlugin<R> {
    fn name(&self) -> &'static str {
        "user_todo_api"
    }
    fn initialization_script(&self) -> Option<String> {
        None
    }

    fn initialize(&mut self, _app: &AppHandle<R>, _config: serde_json::Value) -> PluginResult<()> {
        Ok(())
    }

    fn created(&mut self, _window: Window<R>) {}

    fn on_page_load(&mut self, _window: Window<R>, _payload: PageLoadPayload) {}

    fn extend_api(&mut self, message: Invoke<R>) {
        (self.invoke_handler)(message)
    }
}